package com.reviewit.mbean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;

import org.bson.types.ObjectId;

import com.reviewit.dao.DocumentDao;
import com.reviewit.dao.TagDao;
import com.reviewit.model.Document;
import com.reviewit.model.Tag;
import com.reviewit.util.Util;

@ManagedBean
@SessionScoped
public class TagBean extends GenericBean implements Serializable,
		NavigationRules {
	private static final long serialVersionUID = 1L;

	private DataModel<Tag> tags;
	private Tag tag;
	private TagDao dao;

	public TagBean() {
		super();
		this.log = Logger.getLogger(this.getClass().getName());
		this.dao = TagDao.getInstance();
		this.tag = new Tag();
	}

	public Tag getTag() {
		return tag;
	}

	public void setTag(Tag tag) {
		this.tag = tag;
	}

	public void setTags(DataModel<Tag> tags) {
		this.tags = tags;
	}

	public DataModel<Tag> getTags() {
		List<Tag> list = dao.find().asList();
		tags = new ListDataModel<Tag>(list);
		return tags;
	}

	public List<String> getTopTags(){
		Map<String, Integer> tagsCount = new HashMap<String, Integer>();
		List<String> topTags = new ArrayList<String>();
		Object[] tags;
		try {
			for (Document doc : DocumentDao.getInstance().find()) {
				for (Tag tag : doc.getTags()) {
					if(tagsCount.get(tag.getName()) == null)
						tagsCount.put(tag.getName(), 1);
					else
						tagsCount.put(tag.getName(), tagsCount.get(tag.getName()) + 1);
				}
			}
		} catch (Exception e) {
			log.severe(e.getMessage());
		}
		
		tags = Util.sortMap(tagsCount, false).keySet().toArray();
		
		for(int i = 0; i < tags.length; i++){
			if(topTags.size() == 5)
				break;
			topTags.add(tags[i].toString());
		}
		return topTags;
	}

	public List<String> getNewTags(){
		List<String> newTags = new ArrayList<String>();
		for(Tag tag : TagDao.getInstance().createQuery().order("-creationDate").limit(5).asList())
			newTags.add(tag.getName());
		return newTags;
	}
	
	public void select() {
		setTag(tags.getRowData());
	}

	public List<String> autoComplete(String name) {
		List<String> tags = new ArrayList<String>();
		if(!name.contains(" ")&&!name.contains(",")&&!name.contains(";")&&!name.contains(".")){
			for (Tag tag : dao.createQuery().field("name").startsWith(name.toLowerCase()).asList()){
				tags.add(tag.getName());
			}
		} else{
			if(this.tag==null){
				this.tag = new Tag();
			}
			String tg = name.substring(0,name.length()-1);
			tag.setName(tg);
			tag.setCreationDate(Calendar.getInstance().getTime());
			this.save();
			for (Tag tag : dao.createQuery().field("name").startsWith(tg).asList()){
				tags.add(tag.getName());
			}
		}
		return tags;
	}

	public String findById() {
		Tag obj = dao.findOne("id", tag.getId());
		setTag(obj);

		return NavigationRules.FIND_ENTITY;
	}

	public String saveOrUpdate() {
		Tag obj = dao.findOne("id", tag.getId());
		if (obj == null) {
			return this.update();
		} else {
			return this.save();
		}
	}

	public String save() {
		try {
			tag.setName(tag.getName().toLowerCase().replace(' ', '_'));
			tag.setCreationDate(Calendar.getInstance().getTime());
			dao.save(tag);
		} catch (Exception e) {
			return e.getMessage();
		}

		setTag(new Tag());
		return "Tag saved!";
	}

	public String update() {
		try {
			tag.setName(tag.getName().toLowerCase().replace(' ', '_'));
			dao.save(tag);
		} catch (Exception e) {
			return e.getMessage();
		}

		setTag(new Tag());
		return "Tag updated!";
	}

	public String delete() {
		try {
			dao.delete(tag);
		} catch (Exception e) {
			return e.getMessage();
		}

		setTag(new Tag());
		return "Tag deleted!";
	}

	public String back() {
		return NavigationRules.BACK_CADASTRO;
	}

	public void nnew() {
		setTag(new Tag());
	}
}